package org.zjt.chapter1.io;

import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.util.Attribute;
import io.netty.util.AttributeKey;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;

import java.util.Objects;

/**
 * Description:
 *
 *          childChannel 中的 attr，利用childAttr 来设置属性。 {@link AttributeAndOptionTest#server()}
 *
 *          serverChannel 中的att，利用attr来设置属性。{@link AttributeAndOptionTest#client()}
 *
 *
 * @author juntao.zhang
 * Date: 2018-07-17 下午2:44
 * @see
 */
@Slf4j
public class AttributeAndOptionTest {


    @Test
    public void server() {
        NioEventLoopGroup nioEventLoopGroup = new NioEventLoopGroup();
        try {

            AttributeKey<Integer> attributeKey = AttributeKey.valueOf("name");

            // AttributeKey 设置参数
            ChannelFuture channelFuture = new ServerBootstrap()
                    .childAttr(attributeKey,2323)
                    .group(nioEventLoopGroup)
                    .channel(NioServerSocketChannel.class)
                    .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 500)
                    .option(ChannelOption.TCP_NODELAY, Boolean.FALSE)
                    .option(ChannelOption.SO_KEEPALIVE, Boolean.TRUE)
                    .handler(new LoggingHandler(LogLevel.INFO))
                    .childHandler(new SimpleChannelInboundHandler<ByteBuf>() {
                        @Override
                        protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {
                            Attribute<Integer> attr = ctx.channel().attr(attributeKey);
                            log.info("attrKey:{} \tattr:{}\tmsg:{}", attributeKey.name(), attr.get(), msg);
                        }
                    })
                    .bind(8089).sync();


            channelFuture.channel().closeFuture().sync();

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            nioEventLoopGroup.shutdownGracefully();
        }




    }


    @Test
    public void client() {
        NioEventLoopGroup nioEventLoopGroup = new NioEventLoopGroup();
        try {

            AttributeKey<Integer> id = AttributeKey.newInstance("id");
            ChannelFuture channelFuture = new Bootstrap()
                    .attr(id,232)
                    .group(nioEventLoopGroup)
                    .channel(NioSocketChannel.class)
                    .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 2000)
                    .option(ChannelOption.TCP_NODELAY, Boolean.FALSE)
                    .handler(new SimpleChannelInboundHandler<ByteBuf>() {
                        @Override
                        protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {
                            Integer integer = ctx.channel().attr(id).get();
                            log.info("client msg:{}\t id :{}", msg,integer);
                        }

                        @Override
                        public void channelActive(ChannelHandlerContext ctx) throws Exception {
                            Integer integer = ctx.channel().attr(id).get();
                            log.info("client id :{}", integer);
                            ctx.writeAndFlush(Unpooled.wrappedBuffer(("zhang_" + integer) .getBytes()));
                            super.channelActive(ctx);
                        }
                    })
                    .connect("localhost", 8089).sync();

            channelFuture.channel().closeFuture().sync();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            nioEventLoopGroup.shutdownGracefully();
        }
    }
}
